Latest HTML: https://htmlpreview.github.io/?https://github.com/redhat-developer/docker-java/blob/javaone2015/readme.html
- 1. Preface
- 2. Setup Environments
- 3. Docker Basics
- 4. Run Container
- 5. Deploy Java EE 7 Application (Pre-Built WAR)
- 6. Deploy Java EE 7 Application (Container Linking)
- 7. Build and Deploy Java EE 7 Application
- 8. Multiple Containers Using Docker Compose
- 9. Java EE Application on Docker Swarm Cluster
- 10. Common Docker Commands
- 11. Troubleshooting
- 12. References
1. Preface
Containers are enabling developers to package their applications (and underlying dependencies) in new ways that are portable and work consistently everywhere? On your machine, in production, in your data center, and in the cloud. And Docker has become the de facto standard for those portable containers in the cloud.
Docker is the developer-friendly Linux container technology that enables creation of your stack: OS, JVM, app server, app, and all your custom configuration. So with all it offers, how comfortable are you and your team taking Docker from development to production? Are you hearing developers say, “But it works on my machine!” when code breaks in production?
This lab offers developers an intro-level, hands-on session with Docker, from installation, to exploring Docker Hub, to crafting their own images, to adding Java apps and running custom containers. It will also explain how to use Swarm to orchesorchestrate these containers together. This is a BYOL (bring your own laptop) session, so bring your Windows, OSX, or Linux laptop and be ready to dig into a tool that promises to be at the forefront of our industry for some time to come.
|
Note
|
Latest content of this lab is always at https://github.com/redhat-developer/docker-java |
2. Setup Environments
This section describes what, how, and where to install the software needed for this lab. This lab is designed for a BYOL (Brying Your Own Laptop) style hands-on-lab.
2.1. Hardware
-
Operating System: Mac OS X (10.8 or later), Windows 7 (SP1), Fedora (21 or later)
-
Memory: At least 4 GB+, preferred 8 GB
2.2. Environment (Just needed if you are running with Instructor support)
2.2.1. DNS Server setup Windows
Go to the adapter settings of your pc’s and open the Wireless Network Connection Properties Dialogue. Edit the IPv4 Properties and add the instructor IP (!) as a primary DNS server.
Switch to the cmd and ping classroom.example.com to verify it works.
2.2.2. DNS Server setup Linux/Mac OS
-
Edit
/etc/resolv.conf(Mac OS or Linux) and leave it as:
nameserver <INSTRUCTOR IP ADDRESS>
2.3. Software
-
Java: Oracle JDK 8u45
-
Web Browser
2.4. Git Client
Install Git Client as explained at: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
You can find GIT for Windows at: http://classroom.example.com:8082/downloads/Git-1.9.5-preview20150319.exe
2.5. Maven
-
Download Apache Maven…
-
from Internet: https://maven.apache.org/download.cgi
-
from Instructor: http://classroom.example.com:8082/downloads/apache-maven-3.3.3-bin.zip.
-
-
Unzip to a directory of your choice and add it to the
PATH.
2.6. VirtualBox
Docker currently runs natively on Linux. It can be configured to run in a virtual machine on Mac or Windows. This is why Virtualbox is a requirement for Mac or Windows.
-
Downloads are available
-
from Internet: https://www.virtualbox.org/wiki/Downloads .
-
from Instructor: http://classroom.example.com:8082/downloads/virtualbox/ .
-
|
Warning
|
Linux Users
|
2.7. Vagrant
-
Download Vagrant
-
from Internet: https://www.vagrantup.com/downloads.html
-
from Instructor: http://classroom.example.com:8082/downloads/vagrant/ and install.
-
2.8. Docker Machine
Docker Machine makes it really easy to create Docker hosts on your computer, on cloud providers and inside your own data center. It creates servers, installs Docker on them, then configures the Docker client to talk to them.
#Windows - From Internet
curl https://github.com/docker/machine/releases/download/v0.4.1/docker-machine.exe
#Windows - From Instructor
curl http://classroom.example.com:8082/downloads/docker/docker-machine.exe
# Linux - From Internet
sudo curl -L https://github.com/docker/machine/releases/download/v0.4.1/docker-machine_linux-amd64 -o /usr/local/bin/docker-machine
sudo chmod +x /usr/local/bin/docker-machine
# Linux - From Instructor
sudo curl -L http://classroom.example.com:8082/downloads/docker/docker-machine_linux-amd64 -o /usr/local/bin/docker-machine
sudo chmod +x /usr/local/bin/docker-machine
# Mac - From Internet
sudo curl -L https://github.com/docker/machine/releases/download/v0.4.1/docker-machine_darwin-amd64 -o /usr/local/bin/docker-machine
sudo chmod +x /usr/local/bin/docker-machine
# Mac - From Instructor
sudo curl -L http://classroom.example.com:8082/downloads/docker/docker-machine_darwin-amd64 -o /usr/local/bin/docker-machine
sudo chmod +x /usr/local/bin/docker-machine
2.9. Create Lab Docker Host
-
If you are running this lab without an Instructor, create the Docker Host using the following command:
docker-machine create --driver=virtualbox lab eval "$(docker-machine env lab)"
-
Or Create Docker Host to be used in the lab with an Instructor:
docker-machine create --driver=virtualbox --virtualbox-boot2docker-url=http://classroom.example.com:8082/downloads/boot2docker.iso --engine-insecure-registry=classroom.example.com:5000 lab eval "$(docker-machine env lab)"
Use the following command on Windows:
docker-machine env lab --shell cmd
And then execute all the set commands.
-
To make it easier to start/stop the containers, an entry is added into the host mapping table of your operating system. Find out the IP address of your machine:
docker-machine ip lab
This will provide the IP address associated with the Docker Machine created earlier.
-
Edit
C:\Windows\System32\drivers\etc\hosts(Windows) or/etc/hosts(Mac OS or Linux) and add:
<IP ADDRESS> dockerhost
-
Check if the entry is working:
ping dockerhost
2.10. Docker Client
Docker Client is used to communicate with Docker Host.
# Windows - From Internet
curl -L http://classroom.example.com:8082/downloads/docker/docker-1.8.2.exe -o docker.exe
# Windows - From Internet
curl -L http://test.docker.com.s3.amazonaws.com/builds/Windows/x86_64/docker-1.8.3.exe -o docker.exe
# Linux - From Internet
sudo curl -L https://get.docker.com/builds/Linux/x86_64/docker-latest -o /usr/local/bin/docker
sudo chmod +x /usr/local/bin/docker
# Linux - From Instructor
sudo curl -L http://classroom.example.com:8082/downloads/docker/docker-latest-linux -o /usr/local/bin/docker
sudo chmod +x /usr/local/bin/docker
# Mac - From Internet
sudo curl -L https://get.docker.com/builds/Darwin/x86_64/docker-latest -o /usr/local/bin/docker
sudo chmod +x /usr/local/bin/docker
# Mac - From Instructor
sudo curl -L http://classroom.example.com:8082/downloads/docker/docker-latest-mac -o /usr/local/bin/docker
sudo chmod +x /usr/local/bin/docker
Check if the client is working by executing:
docker ps
Which will return an empty list of containers working. If you get an error message, make sure to have put the docker client into a folder that is contained in your path expression and that you executed the "docker-machine env lab" command according to your operatingsystem.
2.11. WildFly
-
Download WildFly 9.0.1
-
from Internet: http://download.jboss.org/wildfly/9.0.1.Final/wildfly-9.0.1.Final.zip .
-
from Instructor: http://classroom.example.com:8082/downloads/wildfly-9.0.1.Final.zip .
-
-
Install it by extracting the archive.
2.12. JBoss Developer Studio 9.0.0.GA
To install JBoss Developer Studio stand-alone, complete the following steps:
-
From Internet: http://www.jboss.org/download-manager/file/jboss-devstudio-9.0.0.GA-standalone_jar.jar .
-
From Instructor: http://classroom.example.com:8082/downloads/jboss-devstudio-9.0.0.GA-installer-standalone.jar .
-
Start the installer as:
java -jar <JAR FILE NAME>
Follow the on-screen instructions to complete the installation process.
3. Docker Basics
PURPOSE: This chapter introduces the basic terminology of Docker.
Docker is a platform for developers and sysadmins to develop, ship, and run applications. Docker lets you quickly assemble applications from components and eliminates the friction that can come when shipping code. Docker lets you get your code tested and deployed into production as fast as possible.
Docker simplifies software delivery by making it easy to build and share images that contain your application’s entire environment, or application operating system.
What does it mean by an application operating system ?
Your application typically require a specific version of operating system, application server, JDK, database server, may require to tune the configuration files, and similarly multiple other dependencies. The application may need binding to specific ports and certain amount of memory. The components and configuration together required to run your application is what is referred to as application operating system.
You can certainly provide an installation script that will download and install these components. Docker simplifies this process by allowing to create an image that contains your application and infrastructure together, managed as one component. These images are then used to create Docker containers which run on the container virtualization platform, provided by Docker.
Main Components of Docker
Docker has three main components:
-
Images are build component of Docker and a read-only template of application operating system.
-
Containers are run component of Docker, and created from, images.Containers can be run, started, stopped, moved, and deleted.
-
Images are stored, shared, and managed in a registry, the distribution component of Docker. The publically available registry is known as Docker Hub (available at http://hub.docker.com).
In order for these three components to work together, there is Docker Daemon that runs on a host machine and does the heavy lifting of building, running, and distributing Docker containers. In addition, there is Client that is a Docker binary which accepts commands from the user and communicates back and forth with the daemon.
Client communicates with Daemon, either co-located on the same host, or on a different host. It requests the Daemon to pull an image from the repository using pull command. The Daemon then downloads the image from Docker Hub, or whatever registry is configured. Multiple images can be downloaded from the registry and installed on Daemon host. Images are run using run command to create containers on demand.
How does a Docker Image work?
We’ve already seen that Docker images are read-only templates from which Docker containers are launched. Each image consists of a series of layers. Docker makes use of union file systems to combine these layers into a single image. Union file systems allow files and directories of separate file systems, known as branches, to be transparently overlaid, forming a single coherent file system.
One of the reasons Docker is so lightweight is because of these layers. When you change a Docker image—for example, update an application to a new version— a new layer gets built. Thus, rather than replacing the whole image or entirely rebuilding, as you may do with a virtual machine, only that layer is added or updated. Now you don’t need to distribute a whole new image, just the update, making distributing Docker images faster and simpler.
Every image starts from a base image, for example ubuntu, a base Ubuntu image, or fedora, a base Fedora image. You can also use images of your own as the basis for a new image, for example if you have a base Apache image you could use this as the base of all your web application images.
|
Note
|
By default, Docker obtains these base images from Docker Hub. |
Docker images are then built from these base images using a simple, descriptive set of steps we call instructions. Each instruction creates a new layer in our image. Instructions include actions like:
-
Run a command
-
Add a file or directory
-
Create an environment variable
-
Run a process when launching a container
These instructions are stored in a file called a Dockerfile. Docker reads this Dockerfile when you request a build of an image, executes the instructions, and returns a final image.
How does a Container work?
A container consists of an operating system, user-added files, and meta-data. As we’ve seen, each container is built from an image. That image tells Docker what the container holds, what process to run when the container is launched, and a variety of other configuration data. The Docker image is read-only. When Docker runs a container from an image, it adds a read-write layer on top of the image (using a union file system as we saw earlier) in which your application can then run.
3.1. Docker Machine
Machine makes it really easy to create Docker hosts on your computer, on cloud providers and inside your own data center. It creates servers, installs Docker on them, then configures the Docker client to talk to them.
Once your Docker host has been created, it then has a number of commands for managing containers:
-
Start, stop, restart container
-
Upgrade Docker
-
Configure the Docker client to talk to a host
You used Docker Machine already during the attendee setup. We won’t need it too much further on. But if you need to create hosts, it’s a very handy tool to know about. From now on we’re mostly going to use the docker client.
Find out more about the details at the Docker Machine Website.
Check if docker machine is working:
docker-machine -v
It shows the output similar to the one shown below:
docker-machine version 0.4.1 (e2c88d6)
|
Note
|
The exact version may differ based upon how recently the installation was performed. |
3.2. Docker Client
The client communicates with the demon process on your host and let’s you work with images and containers.
Check if your client is working using the following command:
docker -v
It shows the output similar to the following:
Docker version 1.8.2, build 0a8c2e3
|
Note
|
The exact version may differ based upon how recently the installation was performed. |
The most important options you’ll be using frequently are:
-
run- runs a container -
ps- lists containers -
stop- stops a container -
rm- Removes a container
Get a full list of available commands with
docker
A more comprehensive list of commands is also available in Common Docker Commands.
3.3. Verify Docker Configuration
Check if your Docker Host is running:
docker-machine ls
You should see the output similar to:
NAME ACTIVE DRIVER STATE URL SWARM
lab virtualbox Running tcp://192.168.99.101:2376
This machine is shown in “Running” state. If the machine state is stopped, start it with:
docker-machine start lab
After it is started you can find out IP address of your Docker Host with:
docker-machine ip lab
We already did this during the setup document, remember? So, this is a good chance to check, if you already added this IP to your hosts file.
Type:
ping dockerhost
and see if this resolves to the IP address that the docker-machine command printed out. You should see an output as:
> ping dockerhost
PING dockerhost (192.168.99.101): 56 data bytes
64 bytes from 192.168.99.101: icmp_seq=0 ttl=64 time=0.394 ms
64 bytes from 192.168.99.101: icmp_seq=1 ttl=64 time=0.387 ms
If it does, you’re ready to start with the lab.
4. Run Container
The first step in running any application on Docker is to run a container from an image. There are plenty of images available from the official Docker registry (aka Docker Hub). To run any of them, you just have to ask the Docker Client to run it. The client will check if the image already exists on Docker Host. If it exists then it’ll run it, otherwise the host will download the image and then run it.
4.1. Pull Image
Let’s first check, if any images are available:
docker images
At first, this list only contains the Docker swarm image, we used earlier.
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
swarm latest 556c60f87888 33 hours ago 10.2 MB
Now, let’s get a vanilla jboss/wildfly image:
#From Internet
docker pull jboss/wildfly:latest
#From Instructor
docker pull classroom.example.com:5000/wildfly:latest
By default, docker images are retrieved from Docker Hub. In our case, we’re providing a so called private registry via the instructor laptop.
You can see, that Docker is downloading the image with it’s different layers.
|
Note
|
In a traditional Linux boot, the Kernel first mounts the root File System as read-only, checks its integrity, and then switches the whole rootfs volume to read-write mode. When Docker mounts the rootfs, it starts read-only, as in a traditional Linux boot, but then, instead of changing the file system to read-write mode, it takes advantage of a union mount to add a read-write file system over the read-only file system. In fact there may be multiple read-only file systems stacked on top of each other. Consider each one of these file systems as a layer. At first, the top read-write layer has nothing in it, but any time a process creates a file, this happens in the top layer. And if something needs to update an existing file in a lower layer, then the file gets copied to the upper layer and changes go into the copy. The version of the file on the lower layer cannot be seen by the applications anymore, but it is there, unchanged. We call the union of the read-write layer and all the read-only layers a union file system. Figure 3. Docker Layers
|
In our particular case, the jboss/wildfly image extends the jboss/base-jdk:8 image which adds the OpenJDK distribution on top of the jboss/base image. The base image is used for all JBoss community images. It provides a base layer that includes:
-
A jboss user (uid/gid 1000) with home directory set to
/opt/jboss -
A few tools that may be useful when extending the image or installing software, like unzip.
The “jboss/base-jdk:8” image adds:
-
OpenJDK 8 distribution
-
Adds a
JAVA_HOMEenvironment variable
When the download is done, you can list the images again and will see the following:
docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
jboss/wildfly latest 7688aaf382ab 6 weeks ago 581.4 MB
swarm latest 207e8b983242 9 weeks ago 10.2 MB
4.2. Run Container
For now, all we did is pull the container description (aka image) down to our local laptops. Now we want to actually run an instance of the image as a so called "container".
4.2.1. Interactive Container
Typically container run in the background. They are launched and forgotten. And this is the default behaviour for Docker. But there is a way we can make them behave like an instance with an interactive console. To run the WildFly container in an interactive mode.
#From Internet
docker run -it jboss/wildfly
#From Instructor
docker run -it classroom.example.com:5000/wildfly
This will show the output as:
=========================================================================
JBoss Bootstrap Environment
JBOSS_HOME: /opt/jboss/wildfly
JAVA: /usr/lib/jvm/java/bin/java
JAVA_OPTS: -server -XX:+UseCompressedOops -server -XX:+UseCompressedOops -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true
=========================================================================
OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
17:02:58,000 INFO [org.jboss.modules] (main) JBoss Modules version 1.4.3.Final
17:02:58,251 INFO [org.jboss.msc] (main) JBoss MSC version 1.2.6.Final
17:02:58,311 INFO [org.jboss.as] (MSC service thread 1-2) WFLYSRV0049: WildFly Full 9.0.1.Final (WildFly Core 1.0.1.Final) starting
17:02:59,558 INFO [org.jboss.as.controller.management-deprecated] (ServerService Thread Pool -- 11) WFLYCTL0028: Attribute 'job-repository-type' in the resource at address '/subsystem=batch' is deprecated, and may be removed in future version. See the attribute description in the output of the read-resource-description operation to learn more about the deprecation.
17:02:59,560 INFO [org.jboss.as.controller.management-deprecated] (ServerService Thread Pool -- 3) WFLYCTL0028: Attribute 'enabled' in the resource at address '/subsystem=datasources/data-source=ExampleDS' is deprecated, and may be removed in future version. See the attribute description in the output of the read-resource-description operation to learn more about the deprecation.
...
17:03:00,610 INFO [org.wildfly.extension.undertow] (MSC service thread 1-2) WFLYUT0006: Undertow HTTP listener default listening on /0.0.0.0:8080
17:03:00,715 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-2) WFLYJCA0001: Bound data source [java:jboss/datasources/ExampleDS]
17:03:00,881 INFO [org.jboss.ws.common.management] (MSC service thread 1-1) JBWS022052: Starting JBoss Web Services - Stack CXF Server 5.0.0.Final
17:03:00,891 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-2) WFLYDS0013: Started FileSystemDeploymentService for directory /opt/jboss/wildfly/standalone/deployments
17:03:01,131 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://127.0.0.1:9990/management
17:03:01,133 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:9990
17:03:01,138 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly Full 9.0.1.Final (WildFly Core 1.0.1.Final) started in 3431ms - Started 203 of 379 services (210 services are lazy, passive or on-demand)
This shows that the server started correctly, congratulations!
The switches do the following: -i allows to interact with the STDIN and -t attach a TTY to the process. Switches can be combined together and used as -it.
Hit Ctrl+C to stop the container.
4.2.2. Detached Container
Restart the container in detached mode:
#From Internet
docker run --name mywildfly -d jboss/wildfly
#From Instructor
docker run --name mywildfly -d classroom.example.com:5000/wildfly
972f51cc8422eec0a7ea9a804a55a2827b5537c00a6bfd45f8646cb764bc002a
-d, instead of -it, runs the container in detached mode.
The output is the unique id assigned to the container. You can use it to refer to the container in various contexts. Check the logs as:
> docker logs 972f51cc8422eec0a7ea9a804a55a2827b5537c00a6bfd45f8646cb764bc002a
=========================================================================
JBoss Bootstrap Environment
JBOSS_HOME: /opt/jboss/wildfly
. . .
We can check it by issuing the docker ps command which retrieves the images process which are running and the ports engaged by the process:
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7da1c7614edf jboss/wildfly "/opt/jboss/wildfly/ About a minute ago Up About a minute 8080/tcp mywildfly
Noticed the "NAMES" column? This is a quick way of refering to your container. Let’s try to look at the logs again:
docker logs mywildfly
That looks easier.
Also try docker ps -a to see all the containers on this machine.
4.3. Run Container with Default Port
Startup log of the server shows that the server is located in the /opt/jboss/wildfly. It also shows that the public interfaces are bound to the 0.0.0.0 address while the admin interfaces are bound just to localhost. This information will be useful to learn how to customize the server.
docker-machine ip <machine-name> gives us the Docker Host IP address and this was already added to the hosts file. So, we can give it another try by accessing: http://dockerhost:8080. However, this will not work either.
If you want containers to accept incoming connections, you will need to provide special options when invoking docker run. The container, we just started, can’t be accessed by our browser. We need to stop it again and restart with different options.
docker stop mywildfly
Restart the container as:
#From Internet
docker run --name mywildfly-exposed-ports -d -P jboss/wildfly
#From Instructor
docker run --name mywildfly-exposed-ports -d -P classroom.example.com:5000/wildfly
-P map any exposed ports inside the image to a random port on the Docker host. This can be verified as:
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7f41a5a0cfd6 jboss/wildfly "/opt/jboss/wildfly/ 52 seconds ago Up 52 seconds 0.0.0.0:32768->8080/tcp mywildfly-exposed-ports
The port mapping is shown in the PORTS column. Access the WildFly server at http://dockerhost:32768. Make sure to use the correct port number as shown in your case.
|
Note
|
Exact port number may be different in your case. |
4.4. Run Container with Specified Port
Lets stop the previously running container as:
docker stop mywildfly-exposed-ports
Restart the container as:
#From Internet
docker run --name mywildfly-mapped-ports -d -p 8080:8080 jboss/wildfly
#From Instructor
docker run --name mywildfly-mapped-ports -d -p 8080:8080 classroom.example.com:5000/wildfly
The format is -p hostPort:containerPort. This option maps container ports to host ports and allows other containers on our host to access them.
|
Note
|
Docker Port Mapping
Port exposure and mapping are the keys to successful work with Docker. See more about networking on the Docker website Advanced Networking |
Now we’re ready to test http://dockerhost:8080 again. This works with the exposed port, as expected.
Lets stop the previously running container as:
docker stop mywildfly-mapped-ports
4.5. Enabling WildFly Administration
Default WildFly image exposes only port 8080 and thus is not available for administration using either the CLI or Admin Console. Lets expose the ports in different ways.
4.5.1. Default Port Mapping
The following command will override the default command in Docker file, start WildFly, and bind application and management port to all network interfaces.
#From Internet
docker run --name managed-wildfly -P -d jboss/wildfly /opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0
#From Instructor
docker run --name managed-wildfly -P -d classroom.example.com:5000/wildfly /opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0
Accessing WildFly Administration Console require a user in administration realm. A pre-created image, with appropriate username/password credentials, is used to start WildFly as:
#From Internet
docker run --name managed-wildfly-from-image -P -d rafabene/wildfly-admin
#From Instructor
docker run --name managed-wildfly-from-image -P -d classroom.example.com:5000/wildfly-management
-P map any exposed ports inside the image to a random port on Docker host.
Look at the exposed ports as:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5fdedef5573b rafabene/wildfly-admin "/bin/sh -c '/opt/jb 15 seconds ago Up 15 seconds 0.0.0.0:32772->8080/tcp, 0.0.0.0:32771->9990/tcp managed-wildfly-from-image
ee30433b5414 jboss/wildfly "/opt/jboss/wildfly/ 59 seconds ago Up 59 seconds 0.0.0.0:32769->8080/tcp managed-wildfly
Look for the host port that is mapped in the container, 32769 in this case. Access the admin console at http://dockerhost:32769.
|
Note
|
Exact port number may be different in your case. |
The username/password credentials are:
| Field | Value |
|---|---|
Username |
admin |
Password |
docker#admin |
This shows the admin console as:
Additional Ways To Find Port Mapping
The exact mapped port can also be found as:
-
Using
docker port:docker port managed-wildfly-from-imageto see the output as:
0.0.0.0:32769->8080/tcp 0.0.0.0:32770->9990/tcp -
Using
docker inspect:docker inspect --format='{{(index (index .NetworkSettings.Ports "9990/tcp") 0).HostPort}}' managed-wildfly-from-image
4.5.2. Fixed Port Mapping
This management image can also be started with a pre-defined port mapping as:
#From Internet
docker run -p 8080:8080 -p 9990:9990 -d rafabene/wildfly-admin
#From Instructor
docker run -p 8080:8080 -p 9990:9990 -d classroom.example.com:5000/wildfly-management
In this case, Docker port mapping will be shown as:
8080/tcp -> 0.0.0.0:8080
9990/tcp -> 0.0.0.0:9990
4.6. Stop and Remove Container
4.6.1. Stop Container
-
Stop a specific container:
docker stop <CONTAINER ID> -
Stop all the running containers
docker stop `docker ps -aq` -
Stop only the exited containers
docker ps -a -f "exited=-1"
4.6.2. Remove Container
-
Remove a specific container:
docker rm 0bc123a8ece0 -
Remove containers meeting a regular expression
docker ps -a | grep wildfly | awk '{print $1}' | xargs docker rm -
Remove all containers, without any criteria
docker rm `docker ps -aq`
5. Deploy Java EE 7 Application (Pre-Built WAR)
Java EE 7 Movieplex is a standard multi-tier enterprise application that shows design patterns and anti-patterns for a typical Java EE 7 application.
Pull the Docker image that contains WildFly and pre-built Java EE 7 application WAR file as shown:
#From Internet
docker pull arungupta/javaee7-hol
#From Instructor
docker pull classroom.example.com:5000/javaee7-hol
The javaee7-hol Dockerfile is based on jboss/wildfly and adds the movieplex7 application as war file.
Run it:
#From Internet
docker run -it -p 8080:8080 arungupta/javaee7-hol
#From Instructor
docker run -it -p 8080:8080 classroom.example.com:5000/javaee7-hol
See the application in action at http://dockerhost:8080/movieplex7/. The output is shown:
|
Note
|
It might take a while for the container to come up. Wait for the server to complete the startup. |
This uses an in-memory database with WildFly application server as shown in the image:
Only two changes are required to the standard jboss/wildfly image:
-
By default, WildFly starts in Web platform. This Java EE 7 application uses some capabilities from the Full Platform and so WildFly is started in that mode instead as:
CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-c", "standalone-full.xml", "-b", "0.0.0.0"] -
WAR file is copied to the
standalone/deploymentsdirectory as:RUN curl -L https://github.com/javaee-samples/javaee7-hol/raw/master/solution/movieplex7-1.0-SNAPSHOT.war -o /opt/jboss/wildfly/standalone/deployments/movieplex7-1.0-SNAPSHOT.war
6. Deploy Java EE 7 Application (Container Linking)
Deploy Java EE 7 Application (Pre-Built WAR) explained how to use an in-memory database with the application server. This gets you started rather quickly but becomes a bottleneck soon as the database is only in-memory. This means that any changes made to your schema and data are lost when the application server shuts down. In this case, you need to use a database server that resides outside the application server. For example, MySQL as the database server and WildFly as the application server.
This section will show how Docker Container Linking can be used to connect to a service running inside a Docker container via a network port.
-
Start MySQL server as:
#From Internet docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql #From Instructor docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d classroom.example.com:5000/mysql-edefine environment variables that are read by the database at startup and allow us to access the database with this user and password. -
Start WildFly with the deployed Java EE 7 application as:
#From Internet docker run -d --name mywildfly-mysql --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7 #From Instructor docker run -d --name mywildfly-mysql --link mysqldb:db -p 8080:8080 classroom.example.com:5000/wildfly-mysql-javaee7--linktakes two parameters - first is name of the container we’re linking to and second is the alias for the link name.NoteContainer LinkingCreating a link between two containers creates a conduit between a source container and a target container and securely transfer information about source container to target container.
In our case, target container (WildFly) can see information about source container (MySQL). When containers are linked, information about a source container can be sent to a recipient container. This allows the recipient to see selected data describing aspects of the source container. For example, IP address of MySQL server is expoed at $DB_PORT_3306_TCP_ADDR and port of MySQL server is exposed at $DB_PORT_3306_TCP_PORT. These are then used to create the JDBC resource.
See more about container communication on the Docker website Linking Containers Together
-
See the output as:
> curl http://dockerhost:8080/employees/resources/employees <?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>
|
Note
|
If you get a 404 or any other error, wait for a little longer until the containers are started up. |
Lets stop the previously running container as:
docker stop mywildfly-mysql
7. Build and Deploy Java EE 7 Application
Now that you learned a lot about images, containers and how to link them together, it is about time to learn about the different deployment options. Let’s start over with the Java EE 7 sample applications again. Java EE 7 Simple Sample is a trivial Java EE 7 sample application and a perfect way to start.
7.1. Build Application
We’re going to build the application first.
-
Clone the repo:
#From Internet git clone https://github.com/javaee-samples/javaee7-simple-sample.git
#From Instructor git clone http://root:dockeradmin@classroom.example.com:10080/root/javaee7-simple-sample.git
-
Build the application:
cd javaee7-simple-sample/
#From Internet
mvn clean package
#From Instructor
curl http://classroom.example.com:8082/downloads/lab-settings.xml -o settings.xml
mvn -s settings.xml clean package
7.2. Start Application Server
Create a folder to place the deployments and give it write access
mkdir deployments
chmod a+w deployments
Start WildFly server as:
#From Internet
docker run --name wildfly -d -p 8080:8080 -v `pwd`/deployments:/opt/jboss/wildfly/standalone/deployments/:rw jboss/wildfly
#From Instructor
docker run --name wildfly -d -p 8080:8080 -v `pwd`/deployments:/opt/jboss/wildfly/standalone/deployments/:rw classroom.example.com:5000/wildfly
|
Note
|
Windows users need to tweak this a bit and copy the deployments to c:/Users/<USER>/deployments because the directory mappings for boot2docker work differently on those systems. Please update the docker -v argument accordingly. 'docker run --name wildfly -d -p 8080:8080 -v /c/Users/meisele/deployments:/opt/jboss/wildfly/standalone/deployments/:rw [classroom.example.com:5000|jboss]/wildfly' |
This command starts a container named “wildfly”.
The -v flag maps a directory from the host into the container. This will be the directory to put the deployments. rw ensures that the Docker container can write to it.
Check logs to verify if the server has started.
docker logs -f wildfly
Access http://dockerhost:8080 in your browser to make sure the instance is up and running.
Now you’re ready to deploy the application for the first time.
7.3. Configure JBoss Developer Studio
Start JBoss Developer Studio, if not already started.
-
Select ‘Servers’ tab, create a new server adapter
Figure 10. Server adapter -
Assign an existing or create a new WildFly 9.0.0 runtime (changed properties are highlighted.)
Figure 11. WildFly Runtime Properties -
If a new runtime needs to be created, pick the directory for WildFly 9.0.1:
Figure 12. WildFly 9.0.1.Final RuntimeClick on ‘Finish’.
-
Double-click on the newly selected server to configure server properties:
Figure 13. Server propertiesThe host name is specified to ‘dockerhost’. Two properties on the left are automatically propagated from the previous dialog. Additional two properties on the right side are required to disable to keep deployment scanners in sync with the server.
-
Specify a custom deployment folder on Deployment tab of Server Editor
Figure 14. Custom deployment folder -
Right-click on the newly created server adapter and click ‘Start’.
Figure 15. Started server
7.4. Deploy Application Using Shared Volumes
-
Import javaee7-simple-sample application source code using Import → Existing Maven Projects.
-
Right-click on the project, select ‘Run on Server’ and chose the previously created server.
The project runs and displays the start page of the application.
Congratulations!
You’ve deployed your first application to WildFly running in a Docker container from JBoss Developer Studio.
Stop WildFly container when you’re done.
docker stop wildfly
7.5. Deploy Application Using CLI
TThe Command Line Interface (CLI) is a tool for connecting to WildFly instances to manage all tasks from command line environment. Some of the tasks that you can do using the CLI are:
-
Deploy/Undeploy web application in standalone/Domain Mode.
-
View all information about the deployed application on runtime.
-
Start/Stop/Restart Nodes in respective mode i.e. Standalone/Domain.
-
Adding/Deleting resource or subsystems to servers.
Lets use the CLI to deploy javaee7-simple-sample to WildFly running in the container.
-
CLI needs to be locally installed and comes as part of WildFly. This should be available in the previously downloaded WildFly. Unzip into a folder of your choice (e.g.
/Users/<USER>/tools/). This will createwildfly-9.0.0.Finaldirectory here. This folder is referred to $WIDLFY_HOME from here on. Make sure to add the/Users/<USER>/tools/wildfly-9.0.0.Final/binto your $PATH. -
Run the “wildfly-management” image with fixed port mapping as explained in Fixed Port Mapping.
-
Run the
jboss-clicommand and connect to the WildFly instance.
Start WildFly server as:
#From Internet
docker run --name wildfly-managed -d -p 8080:8080 -p 9990:9990 rafabene/wildfly-admin
#From Instructor
docker run --name wildfly-managed -d -p 8080:8080 -p 9990:9990 classroom.example.com:5000/wildfly-management
This command starts a container named “wildfly-managed”.
jboss-cli.sh --controller=dockerhost:9990 -u=admin -p=docker#admin -c
This will show the output as:
[standalone@dockerhost:9990 /]
-
Deploy the application as:
deploy <javaee7-simple-sample PATH>target/javaee7-simple-sample-1.10.war --force
Now you’ve sucessfully used the CLI to remote deploy the Java EE 7 sample application to WildFly running as docker container.
7.6. Deploy Application Using Web Console
WildFly comes with a web-based administration console. It also relies on the same management APIs that are used by JBoss Developer Tools and the CLI. It provides a simple and easy to use web-based console to manage WildFly instance. For a Docker image, it needs to be explicitly enabled as explained in Enabling WildFly Administration. Once enabled, it can be accessed at http://dockerhost:9990.
Username and password credentials are shown in [WildFly_Administration_Credentials].
|
Note
|
You may like to stop and remove the Docker container running WildFly. This can be done as Start a new container as |
Deploy the application using the console with the following steps:
-
Go to ‘Deployments’ tab.
Figure 18. Deployments tab in WildFly Web Console -
Click on ‘Add’ button.
-
On ‘Add Deployment’ screen, take the default of ‘Upload a new deployment’ and click ‘Next>>’.
-
Click on ‘Choose File’, select
<javaee7-simple-sample PATH>/javaee7-simple-sample.warfile on your computer. This would bejavaee7-simple-sample/target/javaee7-simple-sample.warfrom Build Application. -
Click on ‘Next>>’.
-
Select ‘Enable’ checkbox.
Figure 19. Enable a deployment -
Click ‘Finish’.
Figure 20. Java EE 7 Simple Sample Deployed
This will complete the deployment of the Java EE 7 application using Web Console. The output can be seen out http://dockerhost:8080/javaee7-simple-sample and looks like:
7.7. Deploy Application Using Management API
A standalone WildFly process, process can be configured to listen for remote management requests using its “native management interface”. The CLI tool that comes with the application server uses this interface, and user can develop custom clients that use it as well. By default, WildFly management interface listens on 127.0.0.1. When running inside a Docker container, the network interface should be bound to all publicly assigned addresses. This can be easily changed by biding to 0.0.0.0 instead of 127.0.0.1.
-
Start another WildFly instance again:
#From Internet docker run -d --name wildfly -p 8080:8080 -p 9990:9990 rafabene/wildfly-admin #From Instructor docker run -d --name wildfly -p 8080:8080 -p 9990:9990 classroom.example.com:5000/wildfly-managementIn addition to application port 8080, the administration port 9990 is exposed as well. The WildFly image that is used has tweaked the start script such that the management interface is bound to 0.0.0.0.
-
Create a new server adapter in JBoss Developer Studio and name it “WildFly 9.0.0-Management”. Specify the host name as ‘dockerhost’.
-
Click on ‘Next>’ and change the values as shown.
Figure 22. Create New Server Adapter -
Take the default values in ‘Remote System Integration’ and click on ‘Finish’.
-
Change server properties by double clicking on the newly created server adapter. Specify admin credentials (username: docker, password: docker#admin). Note, you need to delete the existing password and use this instead:
Figure 23. Management Login Credentials -
Right-click on the newly created server adapter and click ‘Start’. Status quickly changes to ‘Started’ as shown.
Figure 24. Synchronized WildFly Server -
Right-click on the javaee7-simple-sample project, select ‘Run on Server’ and choose this server. The project runs and displays the start page of the application.
-
Stop WildFly when you’re done.
docker stop wildfly
8. Multiple Containers Using Docker Compose
Docker Compose is a tool for defining and running complex applications with Docker. With Compose, you define a multi-container application in a single file, then spin your application up in a single command which does everything that needs to be done to get it running.
An application using Docker containers will typically consist of multiple containers. With Docker Compose, there is no need to write shell scripts to start your containers. All the containers are defined in a configuration file using services, and then docker-compose script is used to start, stop, and restart the application and all the services in that application, and all the containers within that service. The complete list of commands is:
| Command | Purpose |
|---|---|
|
Build or rebuild services |
|
Get help on a command |
|
Kill containers |
|
View output from containers |
|
Print the public port for a port binding |
|
List containers |
|
Pulls service images |
|
Restart services |
|
Remove stopped containers |
|
Run a one-off command |
|
Set number of containers for a service |
|
Start services |
|
Stop services |
|
Create and start containers |
|
Note
|
According to https://docs.docker.com/compose/install/ "You can run Compose on OS X and 64-bit Linux. It is currently not supported on the Windows operating system." |
8.1. Install docker compose
curl -L https://github.com/docker/compose/releases/download/1.4.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
8.2. Configuration File
-
Entry point to Compose is
docker-compose.yml. Lets use the following file:mysqldb: image: [classroom.example.com:5000/]mysql environment: MYSQL_DATABASE: sample MYSQL_USER: mysql MYSQL_PASSWORD: mysql MYSQL_ROOT_PASSWORD: supersecret mywildfly: image: [classroom.example.com:5000|arungupta]/wildfly-mysql-javaee7 links: - mysqldb:db ports: - 8080This file is available in https://raw.githubusercontent.com/redhat-developer/docker-java/javaone2015/attendees/ and shows:
-
Two services defined by the name
mysqldbandmywildfly -
Image name for each service defined using
image -
Environment variables for the MySQL container are defined in
environment -
MySQL container is linked with WildFly container using
links -
Port forwarding is achieved using
ports
-
8.3. Start Services
-
Save the
docker-compose-internet.ymlasdocker-compose.ymlif you are running from Internet or -
Save the
docker-compose-instructor.ymlasdocker-compose.ymlif you are using images from Instructor. -
All services can be started, in detached mode, by giving the command:
docker-compose up -d
And this shows the output as:
Creating attendees_mysqldb_1... Creating attendees_mywildfly_1...
An alternate compose file name can be specified using
-f.An alternate directory where the compose file exists can be specified using
-p. -
Started services can be verified as:
> docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------- attendees_mysqldb_1 /entrypoint.sh mysqld Up 3306/tcp attendees_mywildfly_1 /opt/jboss/wildfly/customi ... Up 0.0.0.0:32773->8080/tcpThis provides a consolidated view of all the services started, and containers within them.
Alternatively, the containers in this application, and any additional containers running on this Docker host can be verified by using the usual
docker pscommand:> docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3598e545bd2f arungupta/wildfly-mysql-javaee7:latest "/opt/jboss/wildfly/ 59 seconds ago Up 58 seconds 0.0.0.0:32773->8080/tcp attendees_mywildfly_1 b8cf6a3d518b mysql:latest "/entrypoint.sh mysq 2 minutes ago Up 2 minutes 3306/tcp attendees_mysqldb_1 -
Service logs can be seen as:
> docker-compose logs Attaching to attendees_mywildfly_1, attendees_mysqldb_1 mywildfly_1 | => Starting WildFly server mywildfly_1 | => Waiting for the server to boot mywildfly_1 | ========================================================================= mywildfly_1 | mywildfly_1 | JBoss Bootstrap Environment mywildfly_1 | mywildfly_1 | JBOSS_HOME: /opt/jboss/wildfly mywildfly_1 | mywildfly_1 | JAVA: /usr/lib/jvm/java/bin/java mywildfly_1 | mywildfly_1 | JAVA_OPTS: -server -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true mywildfly_1 | . . . mywildfly_1 | 15:40:20,866 INFO [org.jboss.resteasy.spi.ResteasyDeployment] (MSC service thread 1-2) Deploying javax.ws.rs.core.Application: class org.javaee7.samples.employees.MyApplication mywildfly_1 | 15:40:20,914 INFO [org.wildfly.extension.undertow] (MSC service thread 1-2) JBAS017534: Registered web context: /employees mywildfly_1 | 15:40:21,032 INFO [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "employees.war" (runtime-name : "employees.war") mywildfly_1 | 15:40:21,077 INFO [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management mywildfly_1 | 15:40:21,077 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990 mywildfly_1 | 15:40:21,077 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.2.0.Final "Tweek" started in 9572ms - Started 280 of 334 services (92 services are lazy, passive or on-demand) mysqldb_1 | Running mysql_install_db mysqldb_1 | 2015-06-05 15:38:31 0 [Note] /usr/sbin/mysqld (mysqld 5.6.25) starting as process 27 ... mysqldb_1 | 2015-06-05 15:38:31 27 [Note] InnoDB: Using atomics to ref count buffer pool pages . . . mysqldb_1 | 2015-06-05 15:38:40 1 [Note] Event Scheduler: Loaded 0 events mysqldb_1 | 2015-06-05 15:38:40 1 [Note] mysqld: ready for connections. mysqldb_1 | Version: '5.6.25' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL) mysqldb_1 | 2015-06-05 15:40:18 1 [Warning] IP address '172.17.0.24' could not be resolved: Name or service not known
8.4. Verify Application
-
Access the application at http://dockerhost:32773/employees/resources/employees/. This is shown in the browser as:
|
Note
|
Use the port displayed in the docker-compose ps command.
|
8.5. Scale Services
TODO Improve the explanation
You can scale the services up as:
docker-compose scale mywildfly=4 Creating and starting 2... done Creating and starting 3... done Creating and starting 4... done
Check the logs…
docker-compose logs
Check the running instances:
docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------
rafael_mysqldb_1 /entrypoint.sh mysqld Up 3306/tcp
rafael_mywildfly_1 /opt/jboss/wildfly/customi ... Up 0.0.0.0:32773->8080/tcp
rafael_mywildfly_2 /opt/jboss/wildfly/customi ... Up 0.0.0.0:32777->8080/tcp
rafael_mywildfly_3 /opt/jboss/wildfly/customi ... Up 0.0.0.0:32780->8080/tcp
rafael_mywildfly_4 /opt/jboss/wildfly/customi ... Up 0.0.0.0:32781->8080/tcp
You can also decide to reduce the number of running instances:
docker-compose scale mywildfly=2 Stopping rafael_mywildfly_3... done Stopping rafael_mywildfly_4... done Removing rafael_mywildfly_3... done Removing rafael_mywildfly_4... done
8.6. Stop Services
Stop the services as:
docker-compose stop Stopping attendees_mywildfly_1... Stopping attendees_mywildfly_2... Stopping attendees_mysqldb_1...
|
Warning
|
Stopping and starting the containers again will give the following error:
This is expected because the JDBC resource is created during every run of the container. In a real-world application, this would be pre-baked in the configuration already. |
8.7. Remove Containers
Stop the services as:
docker-compose rm Going to remove rafael_mywildfly_4, rafael_mywildfly_3, rafael_mywildfly_2, rafael_mywildfly_1, rafael_mysqldb_1 Are you sure? [yN] y Removing rafael_mywildfly_2... done Removing rafael_mywildfly_1... done Removing rafael_mysqldb_1... done
9. Java EE Application on Docker Swarm Cluster
Docker Swarm is native clustering for Docker. It allows you create and access to a pool of Docker hosts using the full suite of Docker tools. Because Docker Swarm serves the standard Docker API, any tool that already communicates with a Docker daemon can use Swarm to transparently scale to multiple hosts
9.1. Key Components of Docker Swarm
Swarm Manager: Docker Swarm has a Manager, that is a pre-defined Docker Host, and is a single point for all administration. The swarm manager orchestrates and schedules containers on the entire cluster. Currently only a single instance of manager is allowed in the cluster. This is a SPOF for high availability architectures and additional managers will be allowed in a future version of Swarm with #598.
Swarm Nodes: The containers are deployed on Nodes that are additional Docker Hosts. Each Swarm Node must be accessible by the manager, each node must listen to the same network interface (TCP port). Each node runs a Docker Swarm agent that registers the referenced Docker daemon, monitors it, and updates the discovery backend with the node’s status. The containers run on a node.
Scheduler Strategy: Different scheduler strategies (“binpack”, “spread” (default), and “random”) can be applied to pick the best node to run your container. The default strategy optimizes the node for least number of running containers. There are multiple kinds of filters, such as constraints and affinity. This should allow for a decent scheduling algorithm.
Node Discovery Service: By default, Swarm uses hosted discovery service, based on Docker Hub, using tokens to discover nodes that are part of a cluster. However etcd, consul, and ZooKeeper can be also be used for service discovery as well. This is particularly useful if there is no access to Internet, or you are running the setup in a closed network. A new discovery backend can be created as explained here. It would be useful to have the hosted Discovery Service inside the firewall and #660 will discuss this.
Standard Docker API: Docker Swarm serves the standard Docker API and thus any tool that talks to a single Docker host will seamlessly scale to multiple hosts now. That means that if you were using shell scripts using Docker CLI to configure multiple Docker hosts, the same CLI would can now talk to Swarm cluster and Docker Swarm will then act as proxy and run it on the cluster.
There are lots of other concepts but these are the main ones.
9.2. Create a Docker Swarm Cluster
-
The easiest way of using Swarm is, by using the official Docker image:
#From Internet docker run --rm swarm create
#From Instructor docker run --rm classroom.example.com:5000/swarm create
This command returns a discovery token, referred as <TOKEN> in this document, and is the unique cluster id. It will be used when creating master and nodes later. This cluster id is returned by the hosted discovery service on Docker Hub.
It shows the output as:
Unable to find image 'swarm:latest' locally
latest: Pulling from swarm
55b38848634f: Pull complete
fd7bc7d11a30: Pull complete
db039e91413f: Pull complete
1e5a49ab6458: Pull complete
5d9ce3cdadc7: Pull complete
1f26e949f933: Pull complete
e08948058bed: Already exists
swarm:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:0e417fe3f7f2c7683599b94852e4308d1f426c82917223fccf4c1c4a4eddb8ef
Status: Downloaded newer image for swarm:latest
1d528bf0568099a452fef5c029f39b85
+ The last line is the <TOKEN>.
+ NOTE: Make sure to note this cluster id now as there is no means to list it later. This should be fixed with #661.
+ . Swarm is fully integrated with Docker Machine, and so is the easiest way to get started. Let’s create a Swarm Master next:
+
#From Internet
docker-machine create -d virtualbox --swarm --swarm-master --swarm-discovery token://<token> swarm-master
#From Instructor
docker-machine create -d virtualbox --virtualbox-boot2docker-url=http://classroom.example.com:8082/downloads/boot2docker.iso --engine-insecure-registry=classroom.example.com:5000 --swarm --swarm-master --swarm-discovery token://<token> swarm-master
Replace <TOKEN> with the cluster id obtained in the previous step.
--swarm configures the machine with Swarm, --swarm-master configures the created machine to be Swarm master. Swarm master creation talks to the hosted service on Docker Hub and informs that a master is created in the cluster.
-
Connect to this newly created master and find some more information about it:
eval "$(docker-machine env swarm-master)"
docker info
+
NOTE: If you’re on Windows, use the docker-machine env swarm-master command only and copy the output into an editor to replace all appearances of EXPORT with SET and issue the three commands at your command prompt, remove the quotes and all duplicate appearences of "/".
+ This will show the output as:
+
> docker info
Containers: 2
Images: 7
Storage Driver: aufs
Root Dir: /mnt/sda1/var/lib/docker/aufs
Backing Filesystem: extfs
Dirs: 11
Dirperm1 Supported: true
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 4.0.5-boot2docker
Operating System: Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015
CPUs: 1
Total Memory: 996.2 MiB
Name: swarm-master
ID: DLFR:OQ3E:B5P6:HFFD:VKLI:IOLU:URNG:HML5:UHJF:6JCL:ITFH:DS6J
Debug mode (server): true
File Descriptors: 22
Goroutines: 36
System Time: 2015-07-11T00:16:34.29965306Z
EventsListeners: 1
Init SHA1:
Init Path: /usr/local/bin/docker
Docker Root Dir: /mnt/sda1/var/lib/docker
Username: arungupta
Registry: https://index.docker.io/v1/
Labels:
provider=virtualbox
-
Create a Swarm node
#From Internet docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> swarm-node-01
#From Instructor docker-machine create -d virtualbox --virtualbox-boot2docker-url=http://classroom.example.com:8082/downloads/boot2docker.iso --engine-insecure-registry=classroom.example.com:5000 --swarm --swarm-discovery token://<TOKEN> swarm-node-01
Replace <TOKEN> with the cluster id obtained in an earlier step.
Node creation talks to the hosted service at Docker Hub and joins the previously created cluster. This is specified by --swarm-discovery token://… and specifying the cluster id obtained earlier.
. To make it a real cluster, let’s create a second node:
#From Internet docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> swarm-node-02
#From Instructor docker-machine create -d virtualbox --virtualbox-boot2docker-url=http://classroom.example.com:8082/downloads/boot2docker.iso --engine-insecure-registry=classroom.example.com:5000 --swarm --swarm-discovery token://<TOKEN> swarm-node-02
Replace <TOKEN> with the cluster id obtained in the previous step.
-
List all the nodes created so far:
docker-machine ls
This shows the output similar to the one below:
docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM lab virtualbox Running tcp://192.168.99.101:2376 swarm-master * virtualbox Running tcp://192.168.99.102:2376 swarm-master (master) swarm-node-01 virtualbox Running tcp://192.168.99.103:2376 swarm-master swarm-node-02 virtualbox Running tcp://192.168.99.104:2376 swarm-masterThe machines that are part of the cluster have the cluster’s name in the SWARM column, blank otherwise. For example, “lab” and “summit2015” are standalone machines where as all other machines are part of the “swarm-master” cluster. The Swarm master is also identified by (master) in the SWARM column.
-
Connect to the Swarm cluster and find some information about it:
eval "$(docker-machine env --swarm swarm-master)" docker info
This shows the output as:
> docker info Containers: 4 Images: 3 Role: primary Strategy: spread Filters: affinity, health, constraint, port, dependency Nodes: 3 swarm-master: 192.168.99.102:2376 └ Containers: 2 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.022 GiB └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs swarm-node-01: 192.168.99.103:2376 └ Containers: 1 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.022 GiB └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs swarm-node-02: 192.168.99.104:2376 └ Containers: 1 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.022 GiB └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs CPUs: 3 Total Memory: 3.065 GiBThere are 3 nodes – one Swarm master and 2 Swarm nodes. There is a total of 4 containers running in this cluster – one Swarm agent on master and each node, and there is an additional swarm-agent-master running on the master. This can be verified by connecting to the master and listing all the containers.
-
List nodes in the cluster with the following command:
docker run swarm list token://<TOKEN>This shows the output as:
> docker run swarm list token://1d528bf0568099a452fef5c029f39b85 192.168.99.103:2376 192.168.99.104:2376 192.168.99.102:2376
9.3. Deploy Java EE Application to Docker Swarm Cluster
The complete cluster is in place now, and we need to deploy the Java EE application to it.
Swarm takes care for the distribution of deployments across the nodes. The only thing, we need to do is to deploy the application as already explained in Deploy Java EE 7 Application (Container Linking).
-
Start MySQL server as:
#From Internet
docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql
#From Instructor
docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d classroom.example.com:5000/mysql
-e define environment variables that are read by the database at startup and allow us to access the database with this user and password.
-
Start WildFly and deploy Java EE 7 application as:
#From Internet
docker run -d --name mywildfly --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7
#From Instructor
docker run -d --name mywildfly --link mysqldb:db -p 8080:8080 classroom.example.com:5000/wildfly-mysql-javaee7
This is using the Docker Container Linking explained earlier.
-
Check state of the cluster as:
> docker info Containers: 7 Images: 5 Role: primary Strategy: spread Filters: affinity, health, constraint, port, dependency Nodes: 3 swarm-master: 192.168.99.102:2376 └ Containers: 2 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.022 GiB └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs swarm-node-01: 192.168.99.103:2376 └ Containers: 2 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.022 GiB └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs swarm-node-02: 192.168.99.104:2376 └ Containers: 3 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.022 GiB └ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs CPUs: 3 Total Memory: 3.065 GiB
“swarm-node-02” is running three containers and so lets look at the list of running containers:
> eval "$(docker-machine env swarm-node-02)"
> docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
35325d730c97 arungupta/wildfly-mysql-javaee7 "/opt/jboss/wildfly/ 57 seconds ago Up 56 seconds 0.0.0.0:32768->8080/tcp rafael_mywildfly_1
dd3525575b12 mysql "/entrypoint.sh mysq 57 seconds ago Up 56 seconds 3306/tcp rafael_mysqldb_1
e9f655cbcb4b swarm:latest "/swarm join --adver 27 minutes ago Up 27 minutes 2375/tcp swarm-agent
-
Access the application as:
curl http://$(docker-machine ip swarm-node-02):8080/employees/resources/employees
to see the output as:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>
9.4. Deploy Java EE Application to Docker Swarm Cluster using Docker Compose
Multiple Containers Using Docker Compose explains how multi container applications can be easily started using Docker Compose.
-
Connect to ‘swarm-node-02’:
eval "$(docker-machine env swarm-node-02)"
-
Stop the MySQL and WildFly containers:
docker ps -a | grep wildfly | awk '{print $1}' | xargs docker rm -f docker ps -a | grep mysql | awk '{print $1}' | xargs docker rm -f -
Use the
docker-compose.ymlfile explained in Multiple Containers Using Docker Compose to start the containers as:docker-compose up -d Creating wildflymysqljavaee7_mysqldb_1... Creating wildflymysqljavaee7_mywildfly_1...
-
Check the containers running in the cluster as:
eval "$(docker-machine env --swarm swarm-master)" docker info
to see the output as:
docker info
Containers: 7
Images: 5
Role: primary
Strategy: spread
Filters: affinity, health, constraint, port, dependency
Nodes: 3
swarm-master: 192.168.99.102:2376
└ Containers: 2
└ Reserved CPUs: 0 / 1
└ Reserved Memory: 0 B / 1.022 GiB
└ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
swarm-node-01: 192.168.99.103:2376
└ Containers: 2
└ Reserved CPUs: 0 / 1
└ Reserved Memory: 0 B / 1.022 GiB
└ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
swarm-node-02: 192.168.99.104:2376
└ Containers: 3
└ Reserved CPUs: 0 / 1
└ Reserved Memory: 0 B / 1.022 GiB
└ Labels: executiondriver=native-0.2, kernelversion=4.0.5-boot2docker, operatingsystem=Boot2Docker 1.7.0 (TCL 6.3); master : 7960f90 - Thu Jun 18 18:31:45 UTC 2015, provider=virtualbox, storagedriver=aufs
CPUs: 3
Total Memory: 3.065 GiB
-
Connect to ‘swarm-node-02’ again:
eval "$(docker-machine env swarm-node-02)"
and see the list of running containers as:
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
35325d730c97 arungupta/wildfly-mysql-javaee7 "/opt/jboss/wildfly/ 57 seconds ago Up 56 seconds 0.0.0.0:32768->8080/tcp rafael_mywildfly_1
dd3525575b12 mysql "/entrypoint.sh mysq 57 seconds ago Up 56 seconds 3306/tcp rafael_mysqldb_1
e9f655cbcb4b swarm:latest "/swarm join --adver 27 minutes ago Up 27 minutes 2375/tcp swarm-agent
-
Check the logs
docker-compose logs
Add container visualiation using https://github.com/javaee-samples/docker-java/issues/55.
10. Common Docker Commands
Here is the list of commonly used Docker commands:
| Purpose | Command |
|---|---|
Image |
|
Build an image |
|
Install an image |
|
List of installed images |
|
List of installed images (detailed listing) |
|
Remove an image |
|
Remove all untagged images |
|
Remove all images |
|
Remove dangling images |
|
Containers |
|
Run a container |
|
List of running containers |
|
List of all containers |
|
Stop a container |
|
Stop all running containers |
|
List all exited containers with status 1 |
|
Remove a container |
|
Remove container by a regular expression |
|
Remove all exited containers |
|
Remove all containers |
|
Find IP address of the container |
|
Attach to a container |
|
Open a shell in to a container |
|
Get container id for an image by a regular expression |
|
11. Troubleshooting
11.1. Can’t resolve classroom.example.com
-
Make sure to add the instructor IP as DNS server to your system
-
On Windows temporarily disable IPv6 (we’re only supporting IPv4)
11.2. Network Timed Out
Depending upon the network speed and restrictions, you may not be able to download Docker images from Docker Hub. The error message may look like:
$ docker pull arungupta/wildfly-mysql-javaee7
Using default tag: latest
Pulling repository docker.io/arungupta/wildfly-mysql-javaee7
Network timed out while trying to connect to https://index.docker.io/v1/repositories/arungupta/wildfly-mysql-javaee7/images. You may want to check your internet connection or if you are behind a proxy.
This section provide a couple of alternatives to solve this.
11.2.1. Restart Docker Machine
It seems like Docker Machine gets into a strange state and restarting it fixes that.
docker-machine restart <MACHINE_NAME>
eval $(docker-machine env <MACHINE_NAME>)
11.2.2. Loading Images Offline
Images can be downloaded from a previously saved .tar file. All images required for this workshop can be downloaded from:
Load the tar file:
docker load -i <path to image tar file>
For example:
docker load -i arungupta-javaee7-hol.tar
Now docker images should show the image.
11.3. Cannot create Docker Machine on Windows
Double check, that you have the correct version of VirtualBox installed. Clear all host-adapter interfaces in Virtualbox before creating a new machine. Make sure to have git for windows in your path.
Are you not able to create Docker Machine on Windows?
Try starting a cmd with Administrator privileges and then give the command again.
11.4. No route to host
Accessing the WildFly and MySQL sample in Kubernetes gives 404 when you give the command curl http://10.246.1.23:8080/employees/resources/employees/.
This may be resolved by stopping the node and restarting the cluster again:
vagrant halt minion-1
./cluster/kube-up.sh
These commands need to be given in the ‘kubernetes’ directory.
12. References
-
Docker Docs: http://docs.docker.com
-
Kubernetes Docs: https://github.com/kubernetes/kubernetes/tree/master/docs
-
JBoss and Docker: http://www.jboss.org/docker/
-
Latest lab content: https://github.com/javaee-samples/docker-java